#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <mysql/mysql.h>
#include <ctype.h>

#include "../inc/tcp.h"
#include "../inc/register.h"
#include "../inc/cJSON.h"
#include "../inc/agreement.h"

static int is_already_friends(client_info_p client, int user_id, int friend_id);
static int has_pending_application(client_info_p client, int apply_from, int apply_to);
static int get_rejected_application_id(client_info_p client, int apply_from, int apply_to);
static int update_rejected_to_pending(client_info_p client, int apply_id, const char *new_msg);
static int insert_new_friend_application(client_info_p client, int apply_from, int apply_to, const char *apply_msg);
static int handle_add_friend_request(client_info_p client, const char *json_str);
static int db_query_single_int(client_info_p client, const char *sql);
static int db_execute_sql(client_info_p client, const char *sql);
static int get_user_id_by_username(client_info_p client, const char *username, int *out_user_id);

/**
 * 处理添加好友命令入口
 */
void handle_add_friend_cmd(client_info_p client, cJSON *root, cJSON *response)
{
    if (client == NULL || root == NULL || response == NULL)
    {
        printf("错误: handle_add_friend_cmd 输入参数为空\n");
        return;
    }

    char *root_str = cJSON_PrintUnformatted(root);
    if (root_str == NULL)
    {
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_DATA_EXCEPTION);
        cJSON_AddStringToObject(response, "message", "请求数据格式错误");
        return;
    }

    int code = handle_add_friend_request(client, root_str);
    free(root_str);

    switch (code)
    {
    case ADD_FRIEND_SUCCESS:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_SUCCESS);
        cJSON_AddStringToObject(response, "message", "好友申请发送成功，请等待对方回应");
        break;

    case ADD_FRIEND_PARAM_ERROR:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_PARAM_ERROR);
        cJSON_AddStringToObject(response, "message", "参数错误");
        break;

    case ADD_FRIEND_DATA_EXCEPTION:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_DATA_EXCEPTION);
        cJSON_AddStringToObject(response, "message", "数据异常");
        break;

    case ADD_FRIEND_ALREADY_FRIEND:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_ALREADY_FRIEND);
        cJSON_AddStringToObject(response, "message", "双方已是好友，无需重复添加");
        break;

    case ADD_FRIEND_PENDING_APPLY:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_PENDING_APPLY);
        cJSON_AddStringToObject(response, "message", "当前方向已存在未处理的好友申请，无需重复发送");
        break;

    case ADD_FRIEND_DB_ERROR:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_DB_ERROR);
        cJSON_AddStringToObject(response, "message", "数据库错误");
        break;
    case ADD_FRIEND_ALREADY_FROM_NULL:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_ALREADY_FROM_NULL);
        cJSON_AddStringToObject(response, "message", "申请人不存在");
        break;
    case ADD_FRIEND_ALREADY_TO_NULL:
        cJSON_AddNumberToObject(response, "code", ADD_FRIEND_ALREADY_TO_NULL);
        cJSON_AddStringToObject(response, "message", "被申请人不存在");
        break;
    }
}

/**
 * 检查是否已是好友
 */
static int is_already_friends(client_info_p client, int user_id, int friend_id)
{
    char sql[256];
    snprintf(sql, sizeof(sql),
             "SELECT id FROM friend_list WHERE "
             "(user_id = %d AND friend_id = %d) OR "
             "(user_id = %d AND friend_id = %d)",
             user_id, friend_id, friend_id, user_id);

    int result = db_query_single_int(client, sql);
    return (result > 0) ? 1 : (result == 0 ? 0 : -1);
}

/**
 * 检查当前方向是否有未处理申请
 */
static int has_pending_application(client_info_p client, int apply_from, int apply_to)
{
    char sql[256];
    snprintf(sql, sizeof(sql),
             "SELECT id FROM friend_apply "
             "WHERE apply_from = %d AND apply_to = %d AND apply_status = %d",
             apply_from, apply_to, APPLY_PENDING);

    int result = db_query_single_int(client, sql);
    return (result > 0) ? 1 : (result == 0 ? 0 : -1);
}

/**
 * 获取被拒绝的申请ID（用于后续更新）
 * @return 正数=申请ID，0=无拒绝记录，-1=查询失败
 */
static int get_rejected_application_id(client_info_p client, int apply_from, int apply_to)
{
    char sql[256];
    snprintf(sql, sizeof(sql),
             "SELECT id FROM friend_apply "
             "WHERE apply_from = %d AND apply_to = %d AND apply_status = %d "
             "ORDER BY create_time DESC LIMIT 1", // 取最新的一条拒绝记录
             apply_from, apply_to, APPLY_REJECTED);

    return db_query_single_int(client, sql);
}

/**
 * 将被拒绝的申请更新为未处理状态（重置为新申请）
 * @param apply_id 被拒绝的申请ID
 * @param new_msg 新的申请留言（可为空）
 * @return 1=成功，0=失败
 */
static int update_rejected_to_pending(client_info_p client, int apply_id, const char *new_msg)
{
    // 获取当前时间（更新创建时间为重新申请的时间）
    char current_time[32] = {0};
    time_t t = time(NULL);
    struct tm *tm = localtime(&t);
    strftime(current_time, sizeof(current_time), "%Y-%m-%d %H:%M:%S", tm);

    char sql[512];
    snprintf(sql, sizeof(sql),
             "UPDATE friend_apply SET "
             "apply_status = %d, "  // 状态改为待处理
             "apply_msg = '%s', "   // 更新留言
             "create_time = '%s', " // 重置创建时间为当前时间
             "handle_time = NULL "  // 清空处理时间
             "WHERE id = %d",
             APPLY_PENDING,
             new_msg ? new_msg : "",
             current_time,
             apply_id);

    return db_execute_sql(client, sql);
}

/**
 * 插入全新的好友申请（无历史拒绝记录时使用）
 */
static int insert_new_friend_application(client_info_p client, int apply_from, int apply_to, const char *apply_msg)
{
    char current_time[32] = {0};
    time_t t = time(NULL);
    struct tm *tm = localtime(&t);
    strftime(current_time, sizeof(current_time), "%Y-%m-%d %H:%M:%S", tm);

    char sql[512];
    snprintf(sql, sizeof(sql),
             "INSERT INTO friend_apply "
             "(apply_from, apply_to, apply_status, apply_msg, create_time, handle_time) "
             "VALUES (%d, %d, %d, '%s', '%s', NULL)",
             apply_from, apply_to, APPLY_PENDING,
             apply_msg ? apply_msg : "",
             current_time);

    return db_execute_sql(client, sql);
}

/**
 * 处理添加好友请求的核心逻辑
 */
static int handle_add_friend_request(client_info_p client, const char *json_str)
{
    if (client == NULL || json_str == NULL || strlen(json_str) == 0)
    {
        printf("错误: 输入参数为空\n");
        return ADD_FRIEND_PARAM_ERROR;
    }

    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL)
    {
        printf("错误: JSON解析失败: %s\n", cJSON_GetErrorPtr());
        return ADD_FRIEND_DATA_EXCEPTION;
    }

    cJSON *type = cJSON_GetObjectItem(root, "type");
    if (type == NULL || !cJSON_IsString(type) || strcmp(type->valuestring, "add_friend") != 0)
    {
        printf("错误: 无效的请求类型\n");
        cJSON_Delete(root);
        return ADD_FRIEND_PARAM_ERROR;
    }

    cJSON *payload = cJSON_GetObjectItem(root, "payload");
    if (payload == NULL || !cJSON_IsObject(payload))
    {
        printf("错误: 未找到有效的payload数据\n");
        cJSON_Delete(root);
        return ADD_FRIEND_PARAM_ERROR;
    }

    cJSON *apply_from = cJSON_GetObjectItem(payload, "apply_from");
    cJSON *apply_to = cJSON_GetObjectItem(payload, "apply_to");
    cJSON *apply_msg = cJSON_GetObjectItem(payload, "apply_msg");

    if (apply_from == NULL || !cJSON_IsString(apply_from) || strlen(apply_from->valuestring) == 0 ||
        apply_to == NULL || !cJSON_IsString(apply_to) || strlen(apply_to->valuestring) == 0)
    {
        printf("错误: 申请数据不完整或无效\n");
        cJSON_Delete(root);
        return ADD_FRIEND_PARAM_ERROR;
    }

    int from_user_id = 0;
    int to_user_id = 0;

    // 获取申请人ID
    int ret = get_user_id_by_username(client, apply_from->valuestring, &from_user_id);
    if (ret != 0)
    {
        cJSON_Delete(root);
        return (ret == -2) ? ADD_FRIEND_ALREADY_FROM_NULL : ADD_FRIEND_DB_ERROR;
    }

    // 获取被申请人ID
    ret = get_user_id_by_username(client, apply_to->valuestring, &to_user_id);
    if (ret != 0)
    {
        cJSON_Delete(root);
        return (ret == -2) ? ADD_FRIEND_ALREADY_TO_NULL : ADD_FRIEND_DB_ERROR;
    }

    if (from_user_id <= 0 || to_user_id <= 0)
    {
        cJSON_Delete(root);
        return ADD_FRIEND_DB_ERROR;
    }

    // 检查是否已是好友
    int friend_check = is_already_friends(client, from_user_id, to_user_id);
    if (friend_check == 1)
    {
        cJSON_Delete(root);
        return ADD_FRIEND_ALREADY_FRIEND;
    }
    if (friend_check == -1)
    {
        cJSON_Delete(root);
        return ADD_FRIEND_DB_ERROR;
    }

    // 检查当前方向是否有未处理申请
    int pending_check = has_pending_application(client, from_user_id, to_user_id);
    if (pending_check == 1)
    {
        cJSON_Delete(root);
        return ADD_FRIEND_PENDING_APPLY;
    }
    if (pending_check == -1)
    {
        cJSON_Delete(root);
        return ADD_FRIEND_DB_ERROR;
    }

    // 核心逻辑：检查是否有被拒绝的历史申请
    const char *new_msg = (apply_msg && cJSON_IsString(apply_msg)) ? apply_msg->valuestring : "";
    int rejected_id = get_rejected_application_id(client, from_user_id, to_user_id);

    if (rejected_id > 0)
    {
        // 有拒绝记录：更新原记录为新申请状态
        if (update_rejected_to_pending(client, rejected_id, new_msg) == 1)
        {
            printf("提示: 已将历史拒绝申请（ID=%d）更新为新申请\n", rejected_id);
            cJSON_Delete(root);
            return ADD_FRIEND_SUCCESS;
        }
        else
        {
            printf("错误: 更新拒绝申请为新申请失败\n");
            cJSON_Delete(root);
            return ADD_FRIEND_DB_ERROR;
        }
    }
    else if (rejected_id == 0)
    {
        // 无拒绝记录：插入新申请
        if (insert_new_friend_application(client, from_user_id, to_user_id, new_msg) == 1)
        {
            printf("提示: 新好友申请发送成功\n");
            cJSON_Delete(root);
            return ADD_FRIEND_SUCCESS;
        }
        else
        {
            printf("错误: 插入新好友申请失败\n");
            cJSON_Delete(root);
            return ADD_FRIEND_DB_ERROR;
        }
    }
    else
    {
        // 查询拒绝记录失败
        printf("错误: 查询历史拒绝申请失败\n");
        cJSON_Delete(root);
        return ADD_FRIEND_DB_ERROR;
    }
}

/**
 * 数据库查询辅助函数（返回单个整数结果）
 */
static int db_query_single_int(client_info_p client, const char *sql)
{
    if (client->db_conn == NULL || sql == NULL || strlen(sql) == 0)
    {
        printf("db_query_single_int: 参数无效或数据库未连接\n");
        return -1;
    }

    if (mysql_query(client->db_conn, sql) != 0)
    {
        printf("db_query_single_int: SQL执行失败：%s（SQL：%s）\n", mysql_error(client->db_conn), sql);
        return -1;
    }

    MYSQL_RES *result = mysql_store_result(client->db_conn);
    if (result == NULL)
    {
        printf("db_query_single_int: 获取结果集失败：%s（SQL：%s）\n", mysql_error(client->db_conn), sql);
        return -1;
    }

    int ret = 0;
    MYSQL_ROW row = mysql_fetch_row(result);
    if (row != NULL && row[0] != NULL)
    {
        ret = atoi(row[0]);
    }

    mysql_free_result(result);
    return ret;
}

/**
 * 数据库执行辅助函数（INSERT/UPDATE等）
 */
static int db_execute_sql(client_info_p client, const char *sql)
{
    if (client->db_conn == NULL || sql == NULL || strlen(sql) == 0)
    {
        printf("db_execute_sql: 参数无效或数据库未连接\n");
        return 0;
    }

    if (mysql_query(client->db_conn, sql) != 0)
    {
        printf("db_execute_sql: SQL执行失败：%s（SQL：%s）\n", mysql_error(client->db_conn), sql);
        return 0;
    }

    my_ulonglong affected_rows = mysql_affected_rows(client->db_conn);
    if (affected_rows <= 0)
    {
        printf("db_execute_sql: 无数据受影响（SQL：%s）\n", sql);
        return 0;
    }

    return 1;
}

/**
 * 根据用户名查询用户ID
 */
static int get_user_id_by_username(client_info_p client, const char *username, int *out_user_id)
{
    if (client == NULL || username == NULL || strlen(username) == 0 || out_user_id == NULL)
    {
        printf("get_user_id_by_username: 参数无效\n");
        return -1;
    }
    *out_user_id = 0;

    char sql[256];
    snprintf(sql, sizeof(sql),
             "SELECT id FROM `user` WHERE userid = '%s' LIMIT 1",
             username);

    int user_id = db_query_single_int(client, sql);
    if (user_id < 0)
    {
        printf("get_user_id_by_username: 数据库查询失败(SQL:%s)\n", sql);
        return -3;
    }
    else if (user_id == 0)
    {
        printf("get_user_id_by_username: 用户名不存在(username:%s)\n", username);
        return -2;
    }

    *out_user_id = user_id;
    return 0;
}
